# Intoduction

Modelling your applications with [actors](https://en.wikipedia.org/wiki/Actor_model),
you can get two benefits: **messaging** and **supervising** between *actors*.

Actor is a reactive entity with state, which can receive and send messages; actor
state is usually changed with new messages. Every **message** has destination (one or
more actors) and user-defined payload. Message is send with *fire-and-forget*
approach, i.e. sender does not care about further delivery and processing of the
message, like with UDP protocol.

The message delivery is *asynchronous*, as the message is put into the queue, and
will be delivered some time later.

With all that properties it is possible to assemble [concurrent](https://en.wikipedia.org/wiki/Concurrency_(computer_science)) programs.

**Supervising** is more about proper actor initialization order, synchronization and
failure handling. *Synchronization* makes it sure that starting sending messages to
actors is performed when actors are ready. *Failure handling* allows to use different
restart strategies of a failing actor, or group of actors, or even escalate locally
unresolveable problem into upper layers... upto restarting the whole board restart.

`rotor-light` is platform-neutral framework, i.e. it can be build and run on any
plaform, which conforms the requirements (C++17, basically).

# rotor and rotor-light

There is a successful C++ actor microframework [rotor](github.com/basiliscos/cpp-rotor/), 
when a few colleques of mine aske me to have something similar for embedded systems.

The following table highlight the differences

|                              |      rotor light        |  rotor
|:----------------------------:|:-----------------------:|:----------------------:
| max. number of actors        | 64                      | unlimited
| max. number of messages      | compile-time defined    | unlimited
| thread-safety                | no                      | yes
| message priorities           | yes                     | no
| request-response pattern     | no                      | yes
| actors discovery & linking   | no                      | yes
| multiple I/O backends        | no (1)                  | yes
| timers                       | yes (1)                 | yes
| non-intrusiveness (2)        | yes                     | yes
| dynamic allocations          | no                      | yes
| C++ standard                 | C++17                   | C++17
| dependencies                 | no (except, stdlib++)   | [boost](https://www.boost.org/), event-loops
| multiple addresses per actor | no                      | yes
| multiple recipients          | yes, via broadcasting   | yes
| uses RTTI                    | no                      | yes


(1) `rotor-light` needs only "now" function from timer, the time point and
time interval are abstract notions, have to be defined by end-user of the library.

(2) Non-intrusiveness means, that a framework does not owns execution thread: when
all messages have been processed, it just exits as there is nothing to do. That way
it is possible to integrate a framework with other event-loops or enter into
power-save mode for MCU.

There are a lot of useful patterns and explanations in
[rotor](github.com/basiliscos/cpp-rotor/) [documentation](https://basiliscos.github.io/cpp-rotor-docs/index.html),
it is worth familiarize self with it to get some insights.

# building

`rotor-light` uses [cmake](https://cmake.org/) build system. It has no dependencies,
except C++17 core libraries  (e.g. `<tuple>`,`<type_traits>` etc.). Basically, the
framework can be build via


```
mkdir build
cd build
cmake ..
make -j4
```

There are few customization options:

 - `ROTOR_LIGHT_TIMEPOINT` defines the type to be used as timepoint. The default
value is `int64_t`

 - `ROTOR_LIGHT_DURATION` defines the type to be used as time interval. The default
value is `int32_t`

Usage example:

```
cmake -DROTOR_LIGHT_TIMEPOINT=int32_t ..
```

